package org.softmed.rest.server.xstream;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.util.List;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.softmed.persistence.PersistenceManager;
import org.softmed.reflection.utils.FieldInfo;
import org.softmed.reflection.utils.ReflectionUtil;
import org.softmed.rest.config.Application;
import org.softmed.rest.generation.ScafoldFacade;
import org.softmed.rest.generation.fields.GenerationConfig;
import org.softmed.rest.generation.scafold.AppConfig;
import org.softmed.rest.generation.uri.URIBuilder;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

import com.google.inject.Inject;
import com.google.inject.name.Named;

public class URIXMLEditor {

	@Inject
	@Named("URIFIeldName")
	static String uriFieldName;

	ReflectionUtil util = new ReflectionUtil();
	// URIManager uriManager = new URIManager();
//	ListItemToXML listItemToXML = new ListItemToXML();

	DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory
			.newInstance();

//	public String setURIObjectTree(PersistenceManager odbUtil, Object root,
//			String xml, Application app, GenerationConfig genCfg)
//			throws Throwable {
//
//		AppConfig genApp = ScafoldFacade.getApp(app);
//		URIBuilder uriBuilder = genApp.getUriBuilder();
//
//		Document doc = getDocument(xml);
//
//		String uri = uriBuilder.getFullPathAndId(odbUtil, root);
//		if (uri != null)
//			doc.getDocumentElement().setAttribute(uriFieldName, uri);
//
//		String correctName = null;
//		List<FieldInfo> fields = util.getNonNativeFieldInfos(root.getClass());
//		for (FieldInfo fieldInfo : fields) {
//
//			if (List.class.isAssignableFrom(fieldInfo.getType()))
//				continue;
//
//			Object child = fieldInfo.getGetter().invoke(root, null);
//			if (child == null)
//				continue;
//
//			//only add if child node found !!!
//			
////			String childXML = listItemToXML.toXML(child, odbUtil, app);
//			childXML = setURI(odbUtil, child, childXML, uriBuilder);
//
//			String alias = genCfg.getFieldAlias(fieldInfo.getDeclaringClass(),
//					fieldInfo.getName());
//			if (alias == null)
//				alias = util.getHifenizedName(fieldInfo.getName());
//
//			String classAlias = genCfg.getAlias(fieldInfo.getType());
//			if (classAlias == null)
//				classAlias = util.getHifenizedName(fieldInfo.getType()
//						.getSimpleName());
//
//			if (!alias.equals(classAlias))
//				childXML = "\r\n<" + alias + ">\r\n" + childXML + "\r\n</"
//						+ alias + ">\r\n";
//
//			// add text to parent root node
//			Element element = doc.getDocumentElement();
//
//			Document childDoc = getDocument(childXML);
//
//			element.appendChild(doc.adoptNode(childDoc.getDocumentElement()
//					.cloneNode(true)));
//
//		}
//
//		doc.normalize();
//		// TODO fix the absence of newlines
//		String text = toString(doc);
//		return text;
//
//	}

	protected String setURI(PersistenceManager odbUtil, Object root,
			String xml, URIBuilder uriBuilder) throws Throwable {

		Document doc = getDocument(xml);

		String uri = uriBuilder.getFullPathAndId(odbUtil, root);
		if (uri != null)
			doc.getDocumentElement().setAttribute(uriFieldName, uri);

		String text = toString(doc);
		return text;

	}

	public String setURI(PersistenceManager odbUtil, Object root, String xml,
			Application app) throws Throwable {

		AppConfig genApp = ScafoldFacade.getApp(app);
		URIBuilder uriBuilder = genApp.getUriBuilder();

		return setURI(odbUtil, root, xml, uriBuilder);

	}

	private Document getDocument(String xml) throws SAXException, IOException,
			ParserConfigurationException {
		Document doc = documentBuilderFactory.newDocumentBuilder().parse(
				new ByteArrayInputStream((xml).getBytes(XStreamManager.CHAR_SET)));
		return doc;
	}

	public String toString(Document doc) throws Throwable {
		StringWriter sw = new StringWriter();
		Transformer serializer = TransformerFactory.newInstance()
				.newTransformer();
		serializer.transform(new DOMSource(doc), new StreamResult(sw));
		String string = sw.toString();
		string = string.substring(string.indexOf('>') + 1);
		return string;
	}

}
